// chess_spider.Message

// messaging - will always be called by child methods
// todo: add timeout
chess_spider.Message = function( action, getArgs, postArgs, successFunc, failureFunc ) {

	// parameters
	chess_spider.state.session.waiting_msg_arr.push( this );
	this.action = action;
	this.getArgs = getArgs;
	this.postArgs = postArgs;
	this.successFunc = successFunc;
	this.failureFunc = failureFunc;
	this.tx_ts = null;
	this.rx_ts = null;
	this.status = 'waiting';
	this.result = null;

	// can send
	if( chess_spider.state.session.state == 'normal' || chess_spider.state.session.state == this.action ) chess_spider.state.session.waiting_msg_arr.pop().send();
}

// actually send mesage
chess_spider.Message.prototype.send = function() {

	// set state
	chess_spider.state.session.state = 'busy';

	// parameters
	var message = this;
	chess_spider.state.session.sent_msg_arr.push(this);
	this.idx = chess_spider.state.session.sent_msg_arr.indexOf(this);

	// build uri
	this.uri = '.'+this.action+'?';
	this.post = null;
	// add GET
	if( this.getArgs ) {
		//-console.log( 'pulling GET' );
		if( chess_spider.state.session.hash ) this.uri += encodeURIComponent(nonce64.encode(JSON.stringify(this.getArgs)));
		else for( var v in this.getArgs ) this.uri += '&' + v + '=' + encodeURIComponent(this.getArgs[v]);
	}
	// add POST
	if( this.postArgs ) {
		//-console.log( 'pulling POST' );
		if( chess_spider.state.session.hash ) this.post = encodeURIComponent(nonce64.encode(JSON.toString(this.postArgs)));
		else {
			this.post = '';
			for( var v in this.postArgs ) this.post += '&' + v + '=' + encodeURIComponent(this.postArgs[v]);
			this.post = this.post.substr(1);
		}
	}

	// send
	this.tx_ts = new Date();
	this.status = 'sent';
	var xhr = new XMLHttpRequest();
	console.log( 'message sent: ' + this.uri );
	//-if( this.action != 'init' ) return;
	xhr.open(((this.post)?'POST':'GET'),this.uri,false);
	xhr.onreadystatechange=function() {
		if( xhr.readyState==4 ) {

			// bookkeeping
			message.rx_ts = new Date();
			message.status = 'received';
			chess_spider.state.session.state = 'normal';

			// do the dirty
			var v_result = xhr.responseText;
			console.log( 'message result: ' + ((xhr.status==200) ? v_result.substr(0,160) : xhr.status+': '+xhr.statusText) );

			// message received incorrectly
			if( xhr.status != 200 ) {
				message.result = { 'status': 'failure', 'message': xhr.status + ': '+ xhr.statusText };
				if( message.failureFunc )	message.failureFunc( message );
				else				nonblockAlert( 'Failure '+xhr.status+': '+xhr.statusText );
			}

			// message received correctly
			else {
				// parse result
				message.result = JSON.parse( v_result );

				// set new hash
				chess_spider.state.session.hash = message.result.hash;

				// success/failure w//o funcs
				if( message.result.status == 'success' && message.successFunc ) {
					message.successFunc( message );
				}
				else if( message.result.status == 'success' ) {
					null;
				}
				else if( message.result.status != 'success' && message.failureFunc ) {
					message.failureFunc( message );
				}
				else if( message.result.status != 'success' ) {
					nonblockAlert( message.result.status + ': ' + message.result.message );
				}
			}

			// next waiting message
			if( chess_spider.state.session.waiting_msg_arr.length > 0 ) chess_spider.state.session.waiting_msg_arr.pop().send();
		}
		// todo: error condition
	}
	if( this.post ) xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	else		xhr.setRequestHeader('Accept','message/x-jl-formresult');
	xhr.send(this.post);
	return false;
}


// message helper: online / offline
chess_spider.Message.online = function() {
	chess_spider.Message.init();
}
chess_spider.Message.offline = function() {
	chess_spider.Message.state.status = 'offline';
}


// message helper: init
chess_spider.Message.init = function() {

	// first time call
	if( chess_spider.state.session.state == undefined ) {
		chess_spider.state.session =  { 'connect_ts':	null,
					  'state':		'new',
					  'waiting_msg_arr':	new Array(),
					  'sent_msg_arr':	new Array(),
					  'hash':		null,
					  'rand':		Math.floor( Math.random() * 1073741823 )
					  //='rand':		1073741823
	       	};

		// online/offline
		window.addEventListener('online',chess_spider.Message.online,true);
		window.addEventListener('online',chess_spider.Message.offline,true);
	}

	// undo session
	chess_spider.state.session.state = 'init';
	chess_spider.state.session.connect_ts = null;
	chess_spider.state.user = { 'login': null, 'name': null, 'login_ts': null };
	

	// if we're offline
	if( navigator.offline ) {
		chess_spider.session.state = 'offline';
		return;
	}

	// initial message
	new chess_spider.Message( 'init', { 'rand': chess_spider.state.session.rand }, null, function( message ) {

		// connection
		chess_spider.state.session.connect_ts = message.rx_ts;

		// logged in
		if( message.result.login ) {
			chess_spider.state.user.login = message.result.login;
			chess_spider.state.user.name = message.result.name;
			chess_spider.state.user.login_ts = message.result.login_ts;

			// stores.server is now enabled
			chess_spider.stores.server.enabled = true;
		}

		// redisplay header
		chess_spider.local.displayHeader();

	}, function( message ) {

		// redisplay header
		chess_spider.local.displayHeader();

	} );
}

chess_spider.Message.login = function( login, cancel, successFunc, failureFunc ) {
	
	// rid existent login
	chess_spider.state.user.login_ts = null;
	chess_spider.state.user.login = null;
	chess_spider.state.user.name = null;

	// stores.server.login is disabled
	chess_spider.stores.server.enabled = false;

	// build url
	new chess_spider.Message( 'login', { 'login': login, 'cancel': cancel }, null, function( message ) {

		// success
		chess_spider.state.user.login_ts = message.rx_ts;
		chess_spider.state.user.login = message.result.login;
		chess_spider.state.user.name = message.result.name;

		// stores.server.login is enabled
		chess_spider.stores.server.enabled = true;

		// redisplay
		if( successFunc ) successFunc();

	}, function( message ) {
		if( failureFunc ) failureFunc();
	} );
}

// logout
chess_spider.Message.logout = function() {

	// build url
	new chess_spider.Message( 'logout', {}, null, function( message ) {

		// success
		chess_spider.state.user.login_ts = null;
		chess_spider.state.user.login = null;
		chess_spider.state.user.name = null;

		// stores.server.login is disabled
		chess_spider.stores.server.enabled = false;

		chess_spider.local.displayHeader();
	} );
}

// email
chess_spider.Message.loginEmail = function() {

	var email = document.getElementById('cs__email');

	// make sure email entered
	if( email.value.indexOf('@') < 0 ) {
		nonblockAlert( 'please entere email' );
		email.focus();
		return false;
	}

	// build url
	new chess_spider.Message( 'email', { 'email': email.value }, null, null, function( message ) {

		// always notify
		chess_spider.state.user.login_ts = null;
		chess_spider.state.user.login = null;
		chess_spider.state.user.name = null;

		// stores.server.login is disabled
		chess_spider.stores.server.enabled = false;

		chess_spider.local.displayHeader();

		nonblockAlert( message.result.message );
	} );
}

